////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                                                            //
//                                                         WNProject                                                          //
//                                                                                                                            //
//            This file is distributed under the BSD 2-Clause open source license. See License.txt for details.               //
//                                                                                                                            //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#ifndef __WN_TYPE_ELEMENT_H__
#define __WN_TYPE_ELEMENT_H__

#include "WNScripting/inc/WNIdentifierElement.h"

#include <vector>

namespace llvm {
    class Type;
    class StructType;
};

enum WNVariableType {
    eWNTypeInvalid = 0,
    eWNTypeInt,
    eWNTypeFloat,
    eWNTypeBool,
    eWNTypeArray,
    eWNTypeStruct,
    eWNTypeChar,
    eWNTypeString,
    eWNTypeMAX,
    eWNTypeUser
};

template<typename T> struct StructTest {
    static WN_BOOL Test(const T& _first, const T& _second) {
        return(_first == _second);
    }
};

template<typename Tit, typename T, typename S> Tit
    WNFind(Tit _begin, Tit _end, const T& _val) {

    Tit i;

    for(i = _begin; i != _end; ++i) {
        if (S::Test(*i, _val)) {
            break;
        }
    }

    return(i);
}

struct __WNTypeElementInternal {
    WNVariableType mType;
    WNIdentifierElement mUserTypeName;

    union {
        llvm::Type* mLlvmType;
        llvm::StructType* mStructType;
    };

    __WNTypeElementInternal* mSubType;
    std::vector<__WNTypeElementInternal*>* mStructTypes;
    std::vector<WNIdentifierElement>* mSubTypeNames;
    WN_BOOL mIsStruct;
    WN_BOOL mForceHeap;
};

typedef __WNTypeElementInternal* WNTypeElement;

class WNUserTypeCompare {
public:
    WNUserTypeCompare(WNTypeElement _testType) : mType(_testType) {}

    WN_BOOL operator() (const WNTypeElement first) {
        return(mType->mUserTypeName == first->mUserTypeName);
    }

private:
    WNTypeElement mType;
};

#endif // __WN_TYPE_ELEMENT_H__